/** ****************************************************************************
@addtogroup KeyMatrix
@{
*******************************************************************************/

#ifndef _KEY_MATRIX_H_
#define _KEY_MATRIX_H_

#include "button.h"


/// 矩阵键盘按键事件回调函数原型声明
typedef void (*FUNC_onMatrixKeyEventCallback)(uint8_t row, uint8_t col, void *cookie);

/// 矩阵键盘中单个按键的状态
typedef struct {
	uint32_t keyDownTime;			// 按键按下时的时间戳(ms)
	uint8_t onDownTriggered;			// “按下”事件是否已经触发过
	uint8_t onLongPress1Triggered;	// “长按1”事件是否已经触发过
	uint8_t onLongPress2Triggered;	// “长按2”事件是否已经触发过
} matrix_key_state_t;

/// 矩阵键盘
typedef struct {
	/// 行引脚掩码 Bit[0:31] 分别映射 {PA[0:7], PB[0:7], PC[0:7], PD[0:7]}
	uint32_t rowPins; 		
	/// 列引脚掩码 Bit[0:31] 分别映射 {PA[0:7], PB[0:7], PC[0:7], PD[0:7]}	
	uint32_t colPins; 		
	/// 行数
	uint8_t rowCount;
	/// 列数
	uint8_t colCount;
	/// 矩阵按键状态：由应用层根据行列数量，分配内存 !!!
	matrix_key_state_t **keyStates;
	
	/// 是否处于监听状态
	uint8_t listen;
	/// 上一次扫描时，最后是扫行(true)还是扫列(false)
	bool lastScanRowMode;
	/// 轮询任务
	uint16_t pollTaskId;
	
	// “按下”事件回调函数
	FUNC_onMatrixKeyEventCallback onDown;
	void* cookieDown;
	// “弹起”事件回调函数
	FUNC_onMatrixKeyEventCallback onUp;
	void* cookieUp;
	// “点击”事件回调函数
	FUNC_onMatrixKeyEventCallback onClick;
	void* cookieClick;
	// “长按1”事件回调函数
	FUNC_onMatrixKeyEventCallback onLongPress1;
	void* cookieLongPress1;
	// “长按2”事件回调函数
	FUNC_onMatrixKeyEventCallback onLongPress2;
	void* cookieLongPress2;
} driver_key_matrix_t;

/// 矩阵键盘驱动初始化
void key_matrix_init(driver_key_matrix_t *dev, uint32_t rowPins, uint32_t colPins, matrix_key_state_t **keyStates);

/// @brief 挂接事件回调函数
void key_matrix_setupCallbacks(
	driver_key_matrix_t* dev, 
	FUNC_onMatrixKeyEventCallback onDown,        void* cookieDown,
	FUNC_onMatrixKeyEventCallback onUp,          void* cookieUp,
	FUNC_onMatrixKeyEventCallback onClick,       void* cookieClick,
	FUNC_onMatrixKeyEventCallback onLongPress1,  void* cookieLongPress1,
	FUNC_onMatrixKeyEventCallback onLongPress2,  void* cookieLongPress2 );

/// @brief 监听
void key_matrix_listen(driver_key_matrix_t *dev, bool enable);

/// @brief 获取按键状态
ButtonState key_matrix_getState(driver_key_matrix_t* dev, uint8_t row, uint8_t col);


#endif  // _KEY_MATRIX_H_
/// @}
